-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support swap partitions and logical volumes in DiskCustomization (COMPOSER-2400) #1072
Conversation
f96c80d
to
d9448fe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work. I've found a few minor issues, but overall, this looks very nice 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! This is very nice! I have a few inline suggestions/ideas/questions but I don't think there are any blockers, fine to merge to move this forward (or we can iterate here as you prefer).
A bit of a meta comment - splitting 1f9e2a2 (the testdisk move) out beforehand would be something I would have preferred, it would be a very simple review as it just shuffles things around. Then this PR would have been smaller.
pkg/blueprint/disk_customizations.go
Outdated
if p.FSType == "swap" { | ||
// make sure the mountpoint is empty and return | ||
if p.Mountpoint != "" { | ||
return fmt.Errorf("mountpoint for swap partition must be empty") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(super nitpick) maybe add the mountpoint so that the issue is easier to locate (e.g. mountpoint for swap partition must be empty, got %q", p.Mountpoint)
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -55,6 +55,10 @@ func (fs *Filesystem) GetMountpoint() string { | |||
return fs.Mountpoint | |||
} | |||
|
|||
func (fs *Filesystem) GetFSFile() string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as for btrfs, we probably want:
diff --git a/pkg/disk/filesystem_test.go b/pkg/disk/filesystem_test.go
index c97b811c9..a6cc67c09 100644
--- a/pkg/disk/filesystem_test.go
+++ b/pkg/disk/filesystem_test.go
@@ -9,4 +9,5 @@ import (
func TestImplementsInterfacesCompileTimeCheckFilesystem(t *testing.T) {
var _ = disk.Mountable(&disk.Filesystem{})
var _ = disk.UniqueEntity(&disk.Filesystem{})
+ var _ = disk.FSTabEntity(&disk.Filesystem{})
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
pkg/disk/partition_table.go
Outdated
|
||
newpart := Partition{ | ||
Type: partType, | ||
Bootable: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nitpick) as false
is the default, we could just remove it here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
pkg/disk/disk_test.go
Outdated
@@ -164,6 +164,7 @@ func TestCreatePartitionTable(t *testing.T) { | |||
// /boot and subdirectories is exempt from this rule | |||
return nil | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nitpick) This change in the disk: add a test partition table with swap
looks a bit unrelated(?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I disagree. It's definitely completely unrelated.
// populate UUIDs | ||
pt.GenerateUUIDs(rng) | ||
|
||
// print an informative failure message if a new test partition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
|
||
func (MkswapStageOptions) isStageOptions() {} | ||
|
||
func NewMkswapStage(options *MkswapStageOptions, devices map[string]Device) *Stage { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(niptick/followup) - I know its a may sound a bit silly but a tiny test like:
package osbuild
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
)
var expectedJSON = `{
"type": "org.osbuild.mkswap",
"options": {
"uuid": "8a1fc521-02a0-4917-92a9-90a44d7e6503",
"label": "some-label"
},
"devices": {
"root": {
"type": "org.osbuild.loopback"
}
}
}`
func TestNewMkswapStage(t *testing.T) {
devices := make(map[string]Device)
devices["root"] = Device{
Type: "org.osbuild.loopback",
}
options := MkswapStageOptions{
UUID: "8a1fc521-02a0-4917-92a9-90a44d7e6503",
Label: "some-label",
}
stage := NewMkswapStage(&options, devices)
b, err := json.MarshalIndent(stage, "", " ")
assert.NoError(t, err)
assert.Equal(t, expectedJSON, string(b))
}
(also in the tests-as-documentation sense)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -1259,6 +1259,105 @@ func TestNewCustomPartitionTable(t *testing.T) { | |||
}, | |||
}, | |||
}, | |||
"plain+swap": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😍
UUID: fsSpec.UUID, | ||
Label: fsSpec.Label, | ||
stages = append(stages, NewMkfsBtrfsStage(options, stageDevices)) | ||
// Handle subvolumes here directly instead of collecting them in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a line about the /why/ here as well? I assume just because of simplify? Or is there a deeper reason? Maybe // Handle subvolumes directly here instead of in their own case because we can reuse the parent easier this way
(I totally made this up :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
genStage := func(ent disk.Entity, path []disk.Entity) error { | ||
switch e := ent.(type) { | ||
case *disk.Filesystem: | ||
// TODO: extract last device renaming into helper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fwiw, I did a quick experiemnt on this in fa11558 - I would love to see this slightly cleaner (the linked patch is still not nice but avoids some of the repetition and is hopefully a starting point)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left this as a TODO because I didn't want to add extra things and it could use some investigation. Sometimes we need to rename the leaf device and other times we don't, but maybe renaming it always is a good general approach and we can just add it tot he existing function. Alternatively we can have a "rename last device" function. Another alternative is to add an argument to the function to rename the last device to whatever the caller specifies.
I don't know which is cleaner, so I'd rather look into it separately :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, total in a followup (or prereq - not here). Sorry if that wasn't clear!
A new interface FSTabEntity which describes entities that can appear in the /etc/fstab file. This new interface replaces most of the Mountable interface, in which it is now embedded. The new interface will be useful to separate entries that cannot be mounted but do appear in the fstab file (namely, swap areas and swap files). All current Mountables (Filesystem and BtrfsSubvolume) implement GetFSFile() now as an alias to GetMountpoint().
This function is the same idea as ForEachMountable() but for the new FSTabEntity interface. The new function is used in the NewFSTabStageOptions() now which is more appropriate. The distinction will be useful with the addition of swap areas that should appear in /etc/fstab (and therefore, the org.osbuild.fstab stage options) but should not be considered for the mkfs stage generation.
New PayloadEntity for Swap partitions. It resembles a Filesystem, but with fewer fields and fixed values for the fstab entries (fs_file, type, freq, and passno).
Add the SwapPartitionGUID for GPT and DosSwapID for DOS. Register both in the idMap. Refs: - https://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec/ - https://tldp.org/HOWTO/Partition-Mass-Storage-Definitions-Naming-HOWTO/x190.html
Add a new partition table to the TestPartitionTables that includes a swap partition. These partition tables are used in multiple tests in disk_test.go.
Move the TestPartitionTables from the disk tests to the internal/testdisk package. This makes the test partition tables reusable across the project, but also makes it impossible to use them in internal disk tests (import cycle). The PartitionTableFeatures test is therefore moved to the disk_test package instead and the function is exported for testing in the pkg/disk/export_test.go file.
Test the stage option generator for the org.osbuild.fstab stage using the TestPartitionTables. Note that the btrfs subvolumes were missing a name, making the stage option generation fail, so this is also fixed.
Replace the GenMkfsStages() function with a more general GenFsStages(). This new function iterates through all entities, not just mountables, and handles, in addition to filesystem creation (org.osbuild.mkfs.*), btrfs subvolume creation (org.osbuild.btrfs.subvol) and swap (org.osbuild.mkswap). This removes the need for calling the separate GenBtrfsSubVolStage() when generating image pipelines. This change has a minor effect on the org.osbuild.btrfs.subvol stage options in manifests: it changes the name of the device (which is not a functional change) and locks the loopback device (which is not necessary but shouldn't cause issues). Tests have been updated accordingly.
Support setting the fileystem type for a FilesystemTypedCustomization to "swap". When this is set, the Mountpoint should be empty. This makes it possible to create swap areas on either plain partitions or on logical volumes.
When creating plain partitions of logical volumes, if the fstype is "swap", create a Swap payload instead of a Filesystem. Added a new test case for plain with swap and included swap in the btrfs case and a swap logical volume in the lvm case.
d9448fe
to
de9034d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pure awesomeness, thank you! ❤️
This update includes support for swap partitions and logical volumes. See: osbuild/images#1072
This update includes support for swap partitions and logical volumes. See: osbuild/images#1072
This update includes support for swap partitions and logical volumes. See: osbuild/images#1072
This update includes support for swap partitions and logical volumes. See: osbuild/images#1072
This update includes support for swap partitions and logical volumes. See: osbuild/images#1072
This commit adds an integration test for the new swap disk customization that got added to the `images` library in PR osbuild/images#1072
This commit adds an integration test for the new swap disk customization that got added to the `images` library in PR osbuild/images#1072
This commit adds an integration test for the new swap disk customization that got added to the `images` library in PR osbuild/images#1072 Also extends the LVM test to include swap on lvm.
This commit adds an integration test for the new swap disk customization that got added to the `images` library in PR osbuild/images#1072 Also extends the LVM test to include swap on lvm.
This commit adds an integration test for the new swap disk customization that got added to the `images` library in PR osbuild/images#1072 Also extends the LVM test to include swap on lvm.
This commit adds an integration test for the new swap disk customization that got added to the `images` library in PR osbuild/images#1072 Also extends the LVM test to include swap on lvm.
This commit adds an integration test for the new swap disk customization that got added to the `images` library in PR osbuild/images#1072 Also extends the LVM test to include swap on lvm.
This commit adds an integration test for the new swap disk customization that got added to the `images` library in PR osbuild/images#1072 Also extends the LVM test to include swap on lvm.
This commit adds an integration test for the new swap disk customization that got added to the `images` library in PR osbuild/images#1072 Also extends the LVM test to include swap on lvm.
This PR adds support for swap partitions and logical volumes when using the new
disk
blueprint customizations.Internally, swap space is represented by a new
disk.Swap
type (adisk.Element
type) which implements thedisk.PayloadEntity
interface. I also added a new interface:disk.FSTabEntity
. This new entity variant is for representing items that can appear in the fstab file. It differs fromdisk.Mountable
in that it doesn't have a mountpoint, which makes it useful for distinguishing between filesystems and swap areas. It will also be useful for defining swap files as part of the partitioning layout (even though it is not, strictly speaking, part of the partition table).In the customizations, swap is represented by setting the filesystem type to "swap". This is valid for both plain partitions and lvm logical volumes. When the fs type is "swap", the mountpoint must always be empty.